// * var 声明的变量只有全局作用域和函数作用域，没有块作用域。

// ******* 例子1：var 没有块作用域。
if (true) {
	var a = 1
	let b = 2
}

// console.log(a) // 1
// console.log(b) // ReferenceError: b is not defined

// ******* 例子2：对于循环也没有块级作用域也没有循环局部作用域。
for (var i = 0; i < 10; i++) {
	var one = 1
}

console.log(i, one) // 10 1

// ******* 例子3：函数作用域。
function sayHi() {
	if (true) {
		var phrase = 'Hello'
	}

	console.log(phrase) // Hello
}

sayHi()
// console.log(phrase) // ReferenceError: phrase is not defined;

// * var 穿透了 if，for 和其它代码块。因为在早期的 JS 中，块没有词法环境

// ******************************************************************************

// * var 允许使用重复的变量声明
var user = 'Jake'
var user = 'Ben'
console.log(user) // Ben (不会报错，后面的赋值会覆盖前面的值，let 重复声明会报错)

// * var 声明的变量，可以在其声明语句前被使用。
function sayHello() {
	who = 'World'
	console.log(who) // World
	if (true) {
		// var 声明的变量会在函数体开头被定义，与它的位置无关。
		var who
	}
}

sayHello()

// ******************************************************************************

// * var 声明的变量，变量会提升，但是赋值不会，还是要等到代码执行到哪一行了才会被赋值。
function sayLoad() {
	console.log(load) // undefined (不会报错因为load是存在的，但还没被赋值)

	// 这行代码包含两个行为：
	// 1. 首先提升到顶部声明变量。2. 当代码执行到这一行时才赋值。
	var load = 'load'
}

sayLoad()
// * 因为所有的 var 声明都是在函数或全局的开头处理的。可以在任何地方引用它们。但是在它们被赋值之前都是 undefined。

// ******************************************************************************

// * IIFE 模仿块级作用域的方法，被称为“立即调用函数表达式”。(如今不应该再使用 IIFE 了，但是你可以在旧脚本中找到它们。)
;(function () {
	var msg = 'Hello'
	console.log(msg) // Hello
})()
